//
// Created by fairy on 2025/7/28.
//

#ifndef FT6336_HPP
#define FT6336_HPP

#include <gpio.hpp>
#include <i2c.hpp>
#include <hal_delay.hpp>

#include "touch.hpp"

namespace bsp::touch::detail_ft6336
{
        // ========================== 设备状态码 ==========================
        static constexpr uint8_t OK = true; ///< 操作成功标志
        static constexpr uint8_t ERROR = false; ///< 操作失败标志

        // ======================== 设备逻辑状态定义 ========================
        static constexpr uint8_t FALSE = 0; ///< 逻辑假值（基础状态）
        static constexpr uint8_t TRUE = 1; ///< 逻辑真值（基础状态）
        static constexpr uint8_t FALSE1 = 2; ///< 扩展假值1（特殊错误状态）
        static constexpr uint8_t FALSE2 = 3; ///< 扩展假值2（特殊错误状态）


        // ======================== 设备物理层参数 =========================
        static constexpr uint8_t ADDR = 0x71; ///< I2C设备地址（读地址格式，右移一位即7位地址格式）
        static  constexpr  uint16_t HOR = 480;
        static constexpr uint16_t VER = 320;

        // ======================== 寄存器地址定义 =========================
        enum class Reg {
            // --------------------- 基础功能寄存器 --------------------------
            MODE = 0x00,///< 模式控制寄存器（默认值：0x00）
            NUM_FINGER = 0x02,///< 触摸点数量寄存器（0-2个触点）
            // --------------------- 触摸数据寄存器 ----------------------------
            TP1 = 0x03, ///< 第1触摸点数据首地址（包含X/Y坐标等数据）
            TP2 = 0x09, ///< 第2触摸点数据首地址（包含X/Y坐标等数据）
            // --------------------- 设备配置寄存器 ---------------------
            ID_G_FOCALTECH_ID = 0xA8, ///< 厂商ID寄存器（默认值：0x11，只读）
        };

        // ======================== 参数定义 =========================
        enum class Params {
            // --------------------- 面板参数 ---------------------
            PANNEL_ID = 0x11,///< 面板标识码（用于多面板系统识别，默认0x11）
        };

        // ===================== 芯片识别与控制寄存器 ======================
        static constexpr uint8_t ID_G_CIPHER_MID = 0x9F; ///< 芯片代号中字节（默认值：0x26）
        static constexpr uint8_t ID_G_CIPHER_LOW = 0xA0; ///< 芯片代号低字节（0x01:FT6336G，0x02:FT6336U）
        static constexpr uint8_t ID_G_LIB_VERSION = 0xA1; ///< 固件版本寄存器（只读）
        static constexpr uint8_t ID_G_CIPHER_HIGH = 0xA3; ///< 芯片代号高字节（默认值：0x64）
        static constexpr uint8_t ID_G_MODE = 0xA4; ///< 中断模式控制寄存器（配置中断触发方式）

        // ====================== 设备配置寄存器 ==========================
        static constexpr uint8_t ID_G_FOCALTECH_ID = 0xA8; ///< 厂商ID寄存器（默认值：0x11，只读）
        static constexpr uint8_t ID_G_THGROUP = 0x80; ///< 触摸灵敏度寄存器（值越大越灵敏，范围0-80）
        static constexpr uint8_t ID_G_PERIODACTIVE = 0x88; ///< 工作周期寄存器（配置扫描频率，单位10ms）



        /**GPIO引脚定义
        PB5     ------> CTP_RST
        PB6     ------> CTP_INT
        */
        using TOUCH_RST = hal::gpio::pinOld<GPIOB_BASE,GPIO_PIN_5>; // 触摸屏复位引脚
        using i2c = hal::i2c1;
}


namespace bsp::touch
{
    class FT6336 {
    public:
        static uint8_t init()
        {
            using namespace hal;
            using namespace hal::gpio;

            // 初始化i2c1
            detail_ft6336::i2c::init();

            //配置GPIO
            detail_ft6336::TOUCH_RST::init<mode::output_pp,  pull::up>();

            // 重置
            detail_ft6336::TOUCH_RST::clear();
            delay::us(10);
            detail_ft6336::TOUCH_RST::set();
            delay::ms(50);

            std::array<uint8_t, 1> id_reg{100};

            if (const HAL_StatusTypeDef status = i2c1::readMemory(detail_ft6336::ADDR, static_cast<uint16_t>(detail_ft6336::Reg::ID_G_FOCALTECH_ID), id_reg); !status)
            {
                return detail_ft6336::FALSE1; //I2C通信故障
            }
            if (id_reg[0] != static_cast<uint16_t>(detail_ft6336::Params::PANNEL_ID))
            {
                return detail_ft6336::FALSE2; //寄存器值不匹配
            }
            return id_reg[0];
        }

        static bool get_single_point(int16_t &x, int16_t &y)
        {
            using namespace hal;
            std::array<uint8_t, 1> point_number{};
            std::array<uint8_t, 4> touch_pos{};

            // 读取触摸点的数量
            i2c1::readMemory(detail_ft6336::ADDR, static_cast<uint16_t>(detail_ft6336::Reg::NUM_FINGER), point_number); //读点数

            // 如果没有触摸点，返回0
            if (point_number[0] == 0)
            {
                return false;
            }

            // 读取第一个触摸点的坐标
            i2c1::readMemory(detail_ft6336::ADDR, static_cast<uint16_t>(detail_ft6336::Reg::TP1), touch_pos); //读坐标

            // 解析触摸点的坐标 横屏
            x = detail_ft6336::HOR - (static_cast<int16_t>(touch_pos[2] & 0x0F) << 8) | touch_pos[3];
            y = (static_cast<int16_t>(touch_pos[0] & 0x0F) << 8) | touch_pos[1];

            // 返回1表示有触摸点
            return true;
        }
    };
}


#endif //FT6336_HPP
